在稍早前我們聊過 Active Model
可以怎麼玩 attribute
這邊我們來聊聊要怎麼讀取我們設定過的 attributes。
只要你有 include 這兩個 module
class MyCls
include ActiveModel::Model
include ActiveModel::Attributes
# 一定要先 include ActiveModel::Model 才 include ActiveModel::Attributes
# 他們有相依性
# 以下根據您的欄位需求自行規劃
attribute :name, :string
attribute :accept_privacy_policy, :boolean
end
那你的 class 就會有這個 class method MyCls.attribute_types
這其實是個單純的 hash,用來儲存您設定的 attribute 與 type 資料轉換器。
像是上面設定過那些 attribute,那 attribute_types
結構就會像這樣:
pp MyCls.attribute_types
{"name"=>
#<ActiveModel::Type::String:0x00007fdcf8f787d0
@limit=nil,
@precision=nil,
@scale=nil>,
"accept_privacy_policy"=>
#<ActiveModel::Type::Boolean:0x00007fdcf3cf32a8
@limit=nil,
@precision=nil,
@scale=nil>}
key 是 attribute name as string,value 就是繼承自 ActiveModel::Type::Value
系列的 object。
這也是 attribute
跟 attr_accessor
之間的差別:會有一個地方儲存這些定義資訊。
所以,如果善用 attribute_types
這個 class method,以及前篇介紹的 自定義 form builder 我們可以做到
根據所設定的
attribute
欄位名稱與資料型態,自動 render 出表單欄位。
示例如下:
<%= form_for @my_form_object, builder: MyFormBuilder do |form| %>
<% MyCls.attribute_types.each do |attr_name, type| %>
<%= form.render_by_type(attr_name, type) %>
<% end %>
<% end %>
當然,這個 render_by_type
的 method ,就需要您自行在 MyFormBuilder
裡面去規劃了。
根據上一篇,因為 form builder 我們把它繼承 ActionView::Helpers::FormBuilder
的關係,在 instance method 裡面,讀者您完全可以引用每個您所熟知的 form methods,甚至在 method 裡面加上 html 語法在 string 裡面,來自行組出適合您需求的 rendering。
但切記,預設的 form methods 像是 text_area
, text_field
, select
等等,他的回傳值都是 html safe string,如果要跟自定義 string 組合在一起的話,記得您的 string 要再加上 string.html_safe
的 method,這樣才能順利在畫面上 render 出來。